package com.topway.dsmflex.thread.services;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.topway.dsmflex.model.synchro.DataSourceBean;
import com.topway.dsmflex.model.synchro.DataTableBean;
import com.topway.dsmflex.thread.handler.DataHandle;


/**
 * 
 * @author liusy 2013-05-2
 *
 */
public class DbSynchroServices extends AbstractSynchroServices{
	
	
	public DbSynchroServices()
	{
		
	}
	
	private static ThreadLocal<DbSynchroServices> synchroDao= new ThreadLocal<DbSynchroServices>();
	
	
	public synchronized static DbSynchroServices getSynchroDao()
	{
		if(null==synchroDao.get())
		{
			synchroDao.set(new DbSynchroServices());
		}
		return synchroDao.get();
	}
	
	
	
	private int OperatorSource(DataTableBean dt)
	{
		int result=0;
		try {
			if(null!=dt.getDeleteSourceSql()&&!dt.getDeleteSourceSql().equals("")&&null!=dt.getOperatorSource()&&dt.getOperatorSource().equals("DELETE"))
				result=  this.updateTableState( dt.getSourceDataSource(),dt.getDeleteSourceSql());
			  else if(null!=dt.getUpdateSourceSql()&&!dt.getUpdateSourceSql().equals("")&&null!=dt.getOperatorSource()&&dt.getOperatorSource().equals("UPDATE"))
				  result=  this.updateTableState( dt.getSourceDataSource(),dt.getUpdateSourceSql());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
	
	
	
	
	
	public int synchroInsertData(DataTableBean dt) throws SQLException {
		int result = 0;
		this.isDataSources(dt.getSourceDataSource(), dt.getTargetDataSource());
		result = this.synchroInsertData(connSource, connTarget, dt);
		if (result > 0)
		{
			OperatorSource(dt);
			if(null!=dt.getTargetExecuteSql()&&!dt.getTargetExecuteSql().equals(""))
				this.updateTableState(dt.getTargetDataSource(),dt.getTargetExecuteSql());
		}
		return result;
	}

	public int synchroUpdateData( DataTableBean dt) throws SQLException {
		int result = 0;
		this.isDataSources(dt.getSourceDataSource(), dt.getTargetDataSource());
		result = this.synchroUpdateData(connSource, connTarget, dt);
		if (result > 0)
		{
			OperatorSource(dt);
			if(null!=dt.getTargetExecuteSql()&&!dt.getTargetExecuteSql().equals(""))
				this.updateTableState(dt.getTargetDataSource(),dt.getTargetExecuteSql());
		}
		return result;
	}
		  
	public int synchroInsertOrUpdateData(DataTableBean dt) throws SQLException {
		int result = 0;
		this.isDataSources(dt.getSourceDataSource(), dt.getTargetDataSource());
		result = this.synchroInsertOrUpdateData(connSource, connTarget, dt);
		if (result > 0)
		{
			OperatorSource(dt);
			if(null!=dt.getTargetExecuteSql()&&!dt.getTargetExecuteSql().equals(""))
				this.updateTableState(dt.getTargetDataSource(),dt.getTargetExecuteSql());
		}
		return result;
	}
	
	
	public int synchroDeleteData(DataTableBean dt) throws SQLException {
		int result = 0;
		this.isDataSources(dt.getSourceDataSource(), dt.getTargetDataSource());
		result = this.synchroDeleteData(connSource, connTarget, dt);
		if (result > 0)
		{
			OperatorSource(dt);
			if(null!=dt.getTargetExecuteSql()&&!dt.getTargetExecuteSql().equals(""))
				this.updateTableState(dt.getTargetDataSource(),dt.getTargetExecuteSql());
		}
		return result;
	}
	
	

	
	
	
	
	
	
	
	  public int synchroData(Connection sourceConn,Connection targetConn,DataTableBean dt) throws SQLException {
		  int flagResult = 0;
		  Statement stmt =null;
		  ResultSet rs =null;
		  ResultSetMetaData rsmd  = null;
		  
		  Statement stmtTarget =null;
		  ResultSet rsTarget =null;
		  ResultSetMetaData rsmdTarget  = null;
		  
		  Map<String,String> map = new HashMap<String, String>();
		  
		  
			  if(null!=dt.getBeforeTargetSql()&&!"".equals(dt.getBeforeTargetSql())){
				  stmtTarget=  targetConn.createStatement();
				  rsTarget =stmtTarget.executeQuery(dt.getBeforeTargetSql());
				  log.debug(dt.getBeforeTargetSql());
				  rsmdTarget =rsTarget.getMetaData();
				  
				  if(rsTarget.next())
				  {
				      int count = rsmdTarget.getColumnCount();
				      for (int k = 0; k < count; k++) {
				    	 
				    	  map.put(rsmdTarget.getColumnName(k+1).toUpperCase(), getResultStr(rsTarget, rsmdTarget.getColumnType(k+1), rsmdTarget.getColumnName(k+1)));
				      }
				  }
			  }
		  
		//  List<Map<String,String>> listMap = null;
		     Map<String,Integer> mapColumnType = new HashMap<String,Integer>();
		  try {
			  	stmt = sourceConn.createStatement();
			  do
			  {
				  lobMap.clear();
				  listMap.clear();
				  
				  dt.setPageSize(100);
				  String sql = dt.selectSourceNextPage();
				  if(sql.indexOf("{")!=-1&&sql.indexOf("}")!=-1)
				  {
					  for ( Entry<String,String> e : map.entrySet()) {
						  sql= sql.replace( "{"+e.getKey()+"}" ,e.getValue() );
					}
				  }
					  log.debug(sql);
					  
					  System.out.println(stmt.getMaxRows());
				  rs  = stmt.executeQuery(sql);
				 // rs.setFetchSize(dt.getPageSize());java.lang.OutOfMemoryError: Java heap space
				  if(null==rsmd)
				  {
					  rsmd = rs.getMetaData();
				      int count = rsmd.getColumnCount();
				      if(this.dsSource.getDriver().toLowerCase().indexOf("oracle")!=-1)
				    	  count =count-1;
				      for (int k = 0; k < count; k++) {
				         mapColumnType.put(rsmd.getColumnName(k + 1).toUpperCase(), rsmd.getColumnType(k + 1));
				      }
				  }
				  listMap=  getListMap(rs, mapColumnType);
				  if(listMap.size()!=0)
				  {
					  if(null == dataHandle) 
						  dataHandle= new DataHandle(mapColumnType, targetConn,sourceConn, dt,listMap);
					  flagResult = dataHandle.exeDataHandle(listMap,lobMap);
				  }
			  }while(listMap.size()!=0);
				  
		} catch (Exception e) {
			log.error(e.getMessage());
			e.printStackTrace();
		}finally{
			if(null!=dataHandle)
				dataHandle.close();
			dataHandle=null;
			if (null != rs)
				rs.close();
			if (null != stmt)
				stmt.close();
		//	System.gc();
		}
		//return ((dt.getPageIndex()-2)*dt.getPageSize())+flagResult;		
		  return flagResult;
	  }
	  
	  
	  
	  
	  
	
	
	
//	
//	
//	public int synchroInsertData(DataTableBean dt) throws SQLException {
//		this.isDataSources(dt.getSourceDataSource(), dt.getTargetDataSource());
//		return synchroInsertData(connSource, connTarget, dt);
//	}
//
//	public int synchroUpdateData(DataTableBean dt) throws SQLException {
//		this.isDataSources(dt.getSourceDataSource(), dt.getTargetDataSource());
//		return synchroUpdateData(connSource, connTarget, dt);
//	}
//
//	public int synchroInsertOrUpdateData(DataTableBean dt) throws SQLException {
//		this.isDataSources(dt.getSourceDataSource(), dt.getTargetDataSource());
//		return synchroInsertOrUpdateData(connSource, connTarget, dt);
//	}
//
//	public int synchroDeleteData(DataTableBean dt) throws SQLException {
//		this.isDataSources(dt.getSourceDataSource(), dt.getTargetDataSource());
//		return synchroDeleteData(connSource, connTarget, dt);
//	}
		public int updateTableState(DataSourceBean  _dsSource,String sql) throws SQLException
		{
			this.isDataSources(_dsSource,null);
			return updateTableState(connSource,sql);
		}
	
	

	
}
